package com.mec.ServerCluser.core;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.mec.ServerCluser.Interface.IAppUserClient;
import com.mec.ServerCluser.Interface.IUserClientBanlanceChoose;
import com.mec.ServerCluser.RPC.RpcClient;
import com.mec.util.core.ConfigReader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;
import java.util.Map;

/**
 * 用户客户端
 * 数据结构：以服务名称为键，以应用服务器的信息列表为值的Map（所有服务名对应的服务器列表都有）。
 *
 * 功能：向注册中心发送更新服务列表请求，并通过注册中心发来的列表更新自己的数据；
 * 根据均衡负载策略（接口）选择应用服务器
 */
public class AppUserClient implements IAppUserClient {
    private Map<String, List<AppServerDefination>> serviceMap;
    private IUserClientBanlanceChoose banlancedChoose;
    private RpcClient rpcClient;
    private static String registryCenterIp;
    private static int registryCenterAppUserClientPort;
    private Gson gson;

    static {
        //保证线程安全的HashMap
        ConfigReader.init("./net.config.properties");
        registryCenterIp =
                String.valueOf(ConfigReader.getValue("registryCenterIp"));
        registryCenterAppUserClientPort =
                Integer.valueOf(ConfigReader.getValue("registryCenterAppUserClientPort"));
    }

    public AppUserClient() {
        banlancedChoose = new UserClientBanlanceChooseAdapter();
        gson = new GsonBuilder().create();
    }

    @Override
    public String getServiceMapFromRegistryCenter() {
        rpcClient = new RpcClient(registryCenterIp, registryCenterAppUserClientPort);
        String serviceMapInfo = null;
        try {
            IAppUserClient userProxy = rpcClient.getProxy(IAppUserClient.class);
            try{
                serviceMapInfo = userProxy.getServiceMapFromRegistryCenter();
            } catch(UndeclaredThrowableException e){
                //System.out.println("这里出现了异常！");
                //当代理对象拦截到方法时，通过真实对象执行拦截到的方法，如果执行过程中发生了异常
                //则会抛出这种异常，以下是解决方法。
                Throwable t = e.getCause();
                t.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return serviceMapInfo;
    }

    public void updateServiceMap() {
        String serviceMapInfo = getServiceMapFromRegistryCenter();
         Type mapType = new TypeToken<Map<String, List<AppServerDefination>>>(){}.getType();
        serviceMap = gson.fromJson(serviceMapInfo, mapType);
    }

    public void setBanlancedChoose(IUserClientBanlanceChoose banlancedChoose) {
        this.banlancedChoose = banlancedChoose;
    }

    public Map<String, List<AppServerDefination>> getServiceMap() {
        return this.serviceMap;
    }
}
